﻿using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Xml;
using Path = System.Windows.Shapes.Path;

namespace RpaDesigner.Frame
{
    /// <summary>
    /// 设计器框架
    /// </summary>
    /// <Author>黄小邪</Author>
    /// 
    public class DesignerCanvas : Canvas
    {
        private Point? _rubberbandSelectionStartPoint = null;

        private SelectionService _selectionService;

        internal SelectionService SelectionService
        {
            get
            {
                if (_selectionService == null)
                    _selectionService = new SelectionService(this);

                return _selectionService;
            }
        }

        public DesignerCanvas()
        {
            this.AllowDrop = true;
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);

            if (e.Source.Equals(this))
            {
                this._rubberbandSelectionStartPoint = e.GetPosition(this);
                SelectionService.ClearSelection();
                Focus();

                e.Handled = true;
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (e.LeftButton != MouseButtonState.Pressed)
                this._rubberbandSelectionStartPoint = null;

            if (this._rubberbandSelectionStartPoint.HasValue)
            {
                AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
                if (adornerLayer != null)
                {
                    RubberBandAdorner adorner = new RubberBandAdorner(this, _rubberbandSelectionStartPoint);
                    if (adorner != null)
                    {
                        adornerLayer.Add(adorner);
                    }
                }

                e.Handled = true;
            }
        }

        protected override void OnDrop(DragEventArgs e)
        {
            base.OnDrop(e);

            var dragObject = e.Data.GetData(typeof(DragObject)) as DragObject;

            if (dragObject == null || string.IsNullOrEmpty(dragObject.Xaml)) return;

            var content = XamlReader.Load(XmlReader.Create(new StringReader(dragObject.Xaml)));

            if (content != null)
            {
                var newItem = new DesignerItem((content as Path)?.ToolTip + "HH")
                {
                    Content = content,
                    Width = 60,
                    Height = 60
                };

                var position = e.GetPosition(this);
                SetLeft(newItem, Math.Max(0, position.X));
                SetTop(newItem, Math.Max(0, position.Y));

                Canvas.SetZIndex(newItem, this.Children.Count);
                this.Children.Add(newItem);
                SetConnectorDecoratorTemplate(newItem);

                this.SelectionService.SelectItem(newItem);
                newItem.Focus();
            }


            e.Handled = true;
        }

        protected override Size MeasureOverride(Size constraint)
        {
            var size = new Size();

            foreach (UIElement element in this.InternalChildren)
            {
                var left = Canvas.GetLeft(element);
                var top = Canvas.GetTop(element);
                left = double.IsNaN(left) ? 0 : left;
                top = double.IsNaN(top) ? 0 : top;

                //measure desired size for each child
                element.Measure(constraint);

                var desiredSize = element.DesiredSize;
                if (!double.IsNaN(desiredSize.Width) && !double.IsNaN(desiredSize.Height))
                {
                    size.Width = Math.Max(size.Width, left + desiredSize.Width);
                    size.Height = Math.Max(size.Height, top + desiredSize.Height);
                }
            }

            // add margin 
            size.Width += 10;
            size.Height += 10;
            return size;
        }

        private void SetConnectorDecoratorTemplate(DesignerItem item)
        {
            if (item.ApplyTemplate() && item.Content is UIElement)
            {
                ControlTemplate template = DesignerItem.GetConnectorDecoratorTemplate(item.Content as UIElement);
                Control decorator = item.Template.FindName("PART_ConnectorDecorator", item) as Control;
                if (decorator != null && template != null)
                    decorator.Template = template;
            }
        }
    }
}